#include "random-allocation.h"
#include "ns3/log.h"
#include "ns3/simulator.h"
#include "ns3/mobility-model.h"

namespace ns3 {

NS_LOG_COMPONENT_DEFINE("RandomAllocation");

NS_OBJECT_ENSURE_REGISTERED(RandomAllocation);

TypeId RandomAllocation::GetTypeId()
{
    static TypeId tid = TypeId("ns3::RandomAllocation")
        .SetParent<ChannelAllocation>()
        .SetGroupName("SAGINIoV")
        .AddConstructor<RandomAllocation>();
    return tid;
}

RandomAllocation::RandomAllocation()
{
    NS_LOG_FUNCTION(this);
}

RandomAllocation::~RandomAllocation()
{
    NS_LOG_FUNCTION(this);
}

// 实现随机分配算法，但考虑距离限制
std::map<uint32_t, int> RandomAllocation::AllocateChannels()
{
    NS_LOG_FUNCTION(this);
    
    std::map<uint32_t, int> allocation;
    
    if (!m_nodeManager) {
        NS_LOG_ERROR("Node manager is not set");
        return allocation;
    }
    
    // 获取节点
    NodeContainer vehicles = m_nodeManager->GetVehicleNodes();
    NodeContainer groundStations = m_nodeManager->GetGroundStationNodes();
    NodeContainer satellites = m_nodeManager->GetSatelliteNodes();
    
    int numGroundStations = groundStations.GetN();
    int numSatellites = satellites.GetN();
    
    // 获取当前时间
    double currentTime = Simulator::Now().GetSeconds();
    
    // 获取当前活动的车辆数据
    std::vector<VehicleData> vehicleData = m_nodeManager->GetVehicleDataAtTime(currentTime);
    
    // 为每个活跃的车辆分配信道
    for (const auto& vehicle : vehicleData) {
        // 找到对应的节点ID - 修复方法名
        // 在NodeManager类中，正确的方法应该是GetNodeForVehicleId而不是GetNodeIdForVehicle
        uint32_t vehicleNodeId = 0;
        
        // 遍历所有车辆节点，查找匹配vehicleId的节点
        for (uint32_t i = 0; i < vehicles.GetN(); i++) {
            std::string id = m_nodeManager->GetVehicleIdForNode(vehicles.Get(i)->GetId());
            if (id == vehicle.id) {
                vehicleNodeId = vehicles.Get(i)->GetId();
                break;
            }
        }
        
        if (vehicleNodeId == 0) {
            continue; // 无效的节点ID
        }
        
        // 获取车辆节点
        Ptr<Node> vehicleNode = nullptr;
        for (uint32_t i = 0; i < vehicles.GetN(); i++) {
            if (vehicles.Get(i)->GetId() == vehicleNodeId) {
                vehicleNode = vehicles.Get(i);
                break;
            }
        }
        
        if (!vehicleNode) {
            continue;
        }
        
        // 获取车辆移动模型
        Ptr<MobilityModel> vehicleMobility = vehicleNode->GetObject<MobilityModel>();
        if (!vehicleMobility) {
            continue;
        }
        
        // 创建可用信道列表
        std::vector<int> availableChannels;
        
        // 添加地面站信道 (如果允许)
        if (m_allowGroundStationConnection) {
            for (int i = 0; i < numGroundStations; i++) {
                // 获取地面站节点
                Ptr<Node> stationNode = groundStations.Get(i);
                Ptr<MobilityModel> stationMobility = stationNode->GetObject<MobilityModel>();
                
                if (stationMobility) {
                    // 计算距离
                    double distance = vehicleMobility->GetDistanceFrom(stationMobility);
                    
                    // 计算SINR
                    double sinr = CalculateSINR(vehicleNodeId, i);
                    
                    // 检查连接是否可行
                    if (IsGroundStationConnectionFeasible(distance, sinr)) {
                        availableChannels.push_back(i);
                    }
                }
            }
        }
        
        // 添加卫星信道 (如果允许)
        if (m_allowSatelliteConnection) {
            for (int i = 0; i < numSatellites; i++) {
                availableChannels.push_back(numGroundStations + i);
            }
        }
        
        // 如果有可用信道，随机选择一个
        if (!availableChannels.empty()) {
            int randomIndex = std::rand() % availableChannels.size();
            int selectedChannel = availableChannels[randomIndex];
            
            // 将车辆分配给选定的信道
            allocation[vehicleNodeId] = selectedChannel;
            
            // 日志记录
            if (selectedChannel < numGroundStations) {
                NS_LOG_INFO("Vehicle " << vehicle.id << " (node " << vehicleNodeId 
                           << ") allocated to ground station " << selectedChannel);
            } else {
                NS_LOG_INFO("Vehicle " << vehicle.id << " (node " << vehicleNodeId 
                           << ") allocated to satellite " << (selectedChannel - numGroundStations));
            }
        } else {
            NS_LOG_INFO("No available channels for vehicle " << vehicle.id 
                        << " (node " << vehicleNodeId << ")");
        }
    }
    
    return allocation;
}

void RandomAllocation::LogAllocationResults()
{
    NS_LOG_FUNCTION(this);
    
    if (!m_nodeManager) {
        NS_LOG_ERROR("Node manager is not set");
        return;
    }
    
    // 获取当前时间
    double currentTime = Simulator::Now().GetSeconds();
    
    // 获取信道分配
    std::map<uint32_t, int> allocation = m_currentAllocation;
    
    // 获取节点
    NodeContainer groundStations = m_nodeManager->GetGroundStationNodes();
    NodeContainer satellites = m_nodeManager->GetSatelliteNodes();
    
    int numGroundStations = groundStations.GetN();
    
    // 日志输出当前分配情况
    NS_LOG_INFO("Current channel allocation at time " << currentTime << "s:");
    
    for (const auto& [nodeId, channelId] : allocation) {
        std::string vehicleId = m_nodeManager->GetVehicleIdForNode(nodeId);
        
        if (channelId < numGroundStations) {
            NS_LOG_INFO("Vehicle " << vehicleId << " (node " << nodeId 
                       << ") is connected to ground station " << channelId);
        } else {
            NS_LOG_INFO("Vehicle " << vehicleId << " (node " << nodeId 
                       << ") is connected to satellite " << (channelId - numGroundStations));
        }
    }
}

} // namespace ns3
